﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Genesis
{
    class Library
    {
        public static void Save()
        {
            LibrarySerializer libserial = new LibrarySerializer();

            Stream stream = File.Open(LibraryPath + @"\Main.lib", FileMode.Create);
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(stream, libserial);
            stream.Close();
        }
        public static void Load()
        {
            if (Directory.Exists(LibraryPath))
            {
                if (File.Exists(LibraryPath + @"\Main.lib"))
                {
                    LibrarySerializer libserial = new LibrarySerializer();
                    Stream stream = File.Open(LibraryPath + @"\Main.lib", FileMode.Open);
                    BinaryFormatter bf = new BinaryFormatter();

                    libserial = (LibrarySerializer)bf.Deserialize(stream);
                    Songs = libserial.songlist;
                    Playlists = libserial.playLists;

                    stream.Close();
                }
                else
                {
                    Playlists = new Playlist[1];
                    Playlists[0] = new Playlist();
                    Playlists[0].ID = 0;
                    Playlists[0].Name = "Library";
                }
            }
            else
            {
                Directory.CreateDirectory(LibraryPath);
                Playlists = new Playlist[1];
                Playlists[0] = new Playlist();
                Playlists[0].ID = 0;
                Playlists[0].Name = "Library";
            }
        }

        // Methods
        public static void AddSong(Song song)
        {
            if ((song.Location != null) && (song.Location != ""))
                Songs.Add(song);
            Playlists[0].SongList = Songs;
        }
        public static void AddSong(string path)
        {
            AddSong(libBNet.GetInfo(path));
        }
        public static void NewPlaylist(string Name,List<Song> list)
        {
            Playlist[] tmpList = new Playlist[Playlists.Length];
            tmpList = Playlists;

            Playlists = new Playlist[tmpList.Length + 1];
            for (int i = 0; i < tmpList.Length; i++)
            {
                Playlists[i] = tmpList[i];
            }

            Playlists[Playlists.Length - 1] = new Playlist();
            Playlists[Playlists.Length - 1].Name = Name;
            Playlists[Playlists.Length - 1].ID = Playlists.Length -1;

            if (list == null)
                Playlists[Playlists.Length - 1].SongList = new List<Song>();
            else
                Playlists[Playlists.Length - 1].SongList = list;
        }
        public static void RemoveSong(Song song)
        {
            Songs.RemoveAt(IndexOf(song));

            // Search and remove songs in any playlists
            foreach (Playlist p in Playlists)
            {
                for (int i = 0; i < p.SongList.Count; i++)
                {
                    if (p.SongList[i] == song)
                        p.SongList.RemoveAt(i);
                }
            }
        }
        public static void RemovePlaylist(int ID)
        {
            int offset = 0;
            Playlist[] tmpList = new Playlist[Playlists.Length];
            tmpList = Playlists;

            Playlists = new Playlist[tmpList.Length - 1];
            for (int i = 0; i < tmpList.Length; i++)
            {
                if (i == ID)
                    offset++;
                else
                    Playlists[i - offset] = tmpList[i];
            }
        }
        public static void UpdateSong(Song song)
        {
            Song originalSong = songs[IndexOf(song,false)];
            songs[IndexOf(song, false)] = song;

            // Search and update songs in any playlists
            foreach (Playlist p in Playlists)
            {
                for (int i = 0; i < p.SongList.Count; i++)
                {
                    if (p.SongList[i] == originalSong)
                        p.SongList[i] = song;
                }
            }
        }

        // Public Functions
        public static bool RenamePlaylist
        {
            get { return renameplaylist; }
            set { renameplaylist = value; }
        }
        public static int RenamePlaylistID
        {
            get { return renameplaylistid; }
            set { renameplaylistid = value; }
        }
        public static List<Song> CurrentList
        {
            get { return currentlist; }
            set { currentlist = value; }
        }
        public static List<Song> GetLibrary()
        {
            return songs;
        }
        public static List<Song> GetPlaylist(List<Song> List)
        {
            List<Song> returnList = new List<Song>();
            foreach (Song s in List)
            {
                for (int i = 0; i < Songs.Count; i++)
                {
                    if (s.Location == Songs[i].Location)
                    {
                        returnList.Add(s);
                    }
                }
            }
            return returnList;
        }
        public static Playlist[] Playlists;
        public static Song CurrentSong
        {
            get { return currentsong; }
            set { currentsong = value; }
        }
        public static string LibraryPath
        {
            get { return librarypath; }
            set { librarypath = value; }
        }
        
        // Private Functions
        private static bool renameplaylist;
        private static int IndexOf(Song value, bool exact)
        {
            int itemIndex = -1;
            if (exact)
            {
                for (int i = 0; i < Songs.Count; i++)
                {
                    if (Songs[i] == value)
                    {
                        itemIndex = i;
                        break;
                    }
                }
                return itemIndex;
            }
            else
            {
                for (int i = 0; i < Songs.Count; i++)
                {
                    if (Songs[i].Location == value.Location)
                    {
                        itemIndex = i;
                        break;
                    }
                }
                return itemIndex;
            }
        }
        private static int IndexOf(Song value)
        {
            int itemIndex = -1;
            for (int i = 0; i < Songs.Count; i++)
            {
                if (Songs[i] == value)
                {
                    itemIndex = i;
                    break;
                }
            }
            return itemIndex;
        }
        private static int renameplaylistid;
        private static string librarypath;
        private static Song currentsong;
        private static List<Song> currentlist = new List<Song>();
        private static List<Song> Songs
        {
            get { return songs; }
            set { songs = value; }
        }
        private static List<Song> songs = new List<Song>();     
    }

    [Serializable()]
    class Playlist
    {
        // Type
        public Playlist()
        {
        }
        public Playlist(string Name, int ID, List<Song> SongList)
        {
            this.Name = Name;
            this.ID = ID;
            this.SongList = SongList;
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private string name;

        public int ID
        {
            get { return id; }
            set { id = value; }
        }
        private int id;

        public List<Song> SongList
        {
            get { return songlist; }
            set { songlist = value; }
        }
        private List<Song> songlist;
    }

    [Serializable()]
    class LibrarySerializer : ISerializable
    {
        public List<Song> songlist;
        public Playlist[] playLists;

        public LibrarySerializer()
        {
            songlist = Library.GetLibrary();
            playLists = Library.Playlists;
        }

        public LibrarySerializer(SerializationInfo info, StreamingContext context)
        {
            songlist = (List<Song>)info.GetValue("Library", typeof(List<Song>));
            playLists = (Playlist[])info.GetValue("Playlists", typeof(Playlist[]));
        }
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Library", songlist);
            info.AddValue("Playlists", playLists);
        }
    }
}
